package com.qdlc.p2p.biz.borrowworker.worker;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.qdlc.p2p.biz.executer.impl.AwardRepayExecuter;
import com.qdlc.p2p.biz.executer.impl.BondTenderReceiveSuccessExecuter;
import com.qdlc.p2p.biz.executer.impl.BorrowExWaitInterestExecuter;
import com.qdlc.p2p.biz.executer.impl.BorrowRepayCapitalExecuter;
import com.qdlc.p2p.biz.executer.impl.BorrowRepayInterestExecuter;
import com.qdlc.p2p.biz.executer.impl.BorrowRepayLateInterestExecuter;
import com.qdlc.p2p.biz.executer.impl.BorrowRepaySystemLateInterestExecuter;
import com.qdlc.p2p.biz.executer.impl.BorrowRepayTenderCapitalExecuter;
import com.qdlc.p2p.biz.executer.impl.BorrowRepayTenderInterestExecuter;
import com.qdlc.p2p.biz.executer.impl.BorrowRepayTenderLateInterestExecuter;
import com.qdlc.p2p.biz.executer.impl.DeductManageFeeExecuter;
import com.qdlc.p2p.biz.executer.impl.ExperienceExecuter;
import com.qdlc.p2p.biz.executer.impl.ExperienceFullSuccessExecuter;
import com.qdlc.p2p.biz.executer.impl.ExperienceRepayExecuter;
import com.qdlc.p2p.biz.executer.impl.RepayDeductAwardExecuter;
import com.qdlc.p2p.biz.executer.impl.TenderRepaySuccessExecuter;
import com.qdlc.p2p.biz.executer.impl.UpRateFullFailExecuter;
import com.qdlc.p2p.biz.executer.impl.UpRateRepaySuccessExecuter;
import com.qdlc.p2p.biz.executer.impl.UserRedEnvelopeExecuter;
import com.qdlc.p2p.biz.executer.impl.VipUpRateExecuter;
import com.qdlc.p2p.biz.executer.impl.VipUpRateRepayExecuter;
import com.qdlc.p2p.biz.service.AccountService;
import org.apache.log4j.Logger;

import com.qdlc.p2p.biz.executer.AbstractExecuter;
import com.qdlc.p2p.biz.executer.ExecuterHelper;
import com.qdlc.p2p.biz.service.BorrowService;
import com.qdlc.p2p.biz.task.ConcurrentUtil;
import com.qdlc.p2p.biz.tpp.TppBaseInterface;
import com.qdlc.p2p.biz.tpp.TppServiceFactory;
import com.qdlc.p2p.common.constant.BorrowAwardType;
import com.qdlc.p2p.common.constant.BorrowCategory;
import com.qdlc.p2p.common.constant.BorrowRepaymentStatus;
import com.qdlc.p2p.common.constant.BorrowStatus;
import com.qdlc.p2p.common.constant.BorrowStyle;
import com.qdlc.p2p.common.constant.BorrowTenderStatus;
import com.qdlc.p2p.common.constant.BorrowTimeType;
import com.qdlc.p2p.common.constant.BorrowType;
import com.qdlc.p2p.common.constant.Global;
import com.qdlc.p2p.common.constant.UserType;
import com.qdlc.p2p.common.constant.VerifyLogType;
import com.qdlc.p2p.common.constant.VerifyResult;
import com.qdlc.p2p.common.constant.VerifyType;
import com.qdlc.p2p.common.exception.BorrowException;
import com.qdlc.p2p.common.exception.BusinessException;
import com.qdlc.p2p.common.util.BeanUtil;
import com.qdlc.p2p.common.util.BigDecimalUtil;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.StringUtil;
import com.qdlc.p2p.common.util.code.MD5;
import com.qdlc.p2p.dal.checkrule.AutoTenderConfRuleCheck;
import com.qdlc.p2p.dal.checkrule.BorrowAprLimitRuleCheck;
import com.qdlc.p2p.dal.checkrule.BorrowManageFeeRuleCheck;
import com.qdlc.p2p.dal.common.RuleCheckHelper;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.common.SystemConfigHelper.Nid;
import com.qdlc.p2p.dal.dao.AccountDao;
import com.qdlc.p2p.dal.dao.BondCollectionDao;
import com.qdlc.p2p.dal.dao.BondTenderDao;
import com.qdlc.p2p.dal.dao.BorrowCollectionDao;
import com.qdlc.p2p.dal.dao.BorrowDao;
import com.qdlc.p2p.dal.dao.BorrowRepaymentDao;
import com.qdlc.p2p.dal.dao.BorrowTenderDao;
import com.qdlc.p2p.dal.dao.UserCacheDao;
import com.qdlc.p2p.dal.dao.UserIdentifyDao;
import com.qdlc.p2p.dal.dao.UserVipDao;
import com.qdlc.p2p.dal.dao.UserVipGrowthLogDao;
import com.qdlc.p2p.dal.dao.UserVipLevelDao;
import com.qdlc.p2p.dal.dao.VerifyLogDao;
import com.qdlc.p2p.dal.dto.Account;
import com.qdlc.p2p.dal.dto.Bond;
import com.qdlc.p2p.dal.dto.BondCollection;
import com.qdlc.p2p.dal.dto.BondTender;
import com.qdlc.p2p.dal.dto.Borrow;
import com.qdlc.p2p.dal.dto.BorrowCollection;
import com.qdlc.p2p.dal.dto.BorrowConfig;
import com.qdlc.p2p.dal.dto.BorrowRepayment;
import com.qdlc.p2p.dal.dto.BorrowTender;
import com.qdlc.p2p.dal.dto.Operator;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.dto.UserCache;
import com.qdlc.p2p.dal.dto.UserIdentify;
import com.qdlc.p2p.dal.dto.UserVip;
import com.qdlc.p2p.dal.dto.UserVipGrowthLog;
import com.qdlc.p2p.dal.dto.UserVipLevel;
import com.qdlc.p2p.dal.dto.VerifyLog;
import com.qdlc.p2p.dal.model.BorrowModel;
import com.qdlc.p2p.dal.model.TppAccountModel;
import com.qdlc.p2p.dal.model.TppModel;
import com.qdlc.p2p.dal.model.UserVipGrowthLogModel;
import com.qdlc.p2p.dal.model.UserVipLevelModel;
import com.qdlc.p2p.dal.model.interest.EachPlan;
import com.qdlc.p2p.dal.model.interest.InstallmentRepaymentCalculator;
import com.qdlc.p2p.dal.model.interest.InterestCalculator;
import com.qdlc.p2p.dal.model.interest.MonthlyInterestCalculator;
import com.qdlc.p2p.dal.model.interest.OnetimeRepaymentCalculator;
import com.qdlc.p2p.dal.util.SystemConfigs;
import com.qdlc.p2p.dal.util.UserUtils;

public class BaseBorrowWorker implements BorrowWorker {

	@SuppressWarnings("unused")
	private static final long serialVersionUID = 5486891425298146179L;

	private final static Logger logger = Logger.getLogger(BaseBorrowWorker.class);
	
	protected Borrow data;

	protected BorrowConfig config;

	protected boolean flag;

	protected List<BorrowRepayment> repaymentList;

	protected List<BorrowCollection> collectionList;

	/**
	 * 添加构造函数用来判断是否是满标复审
	 * 
	 * @param data
	 * @param config
	 * @param flag
	 */
	public BaseBorrowWorker(Borrow data, BorrowConfig config, boolean flag) {
		if (data != null && data.getId() > 0) {
			BorrowDao borrowDao = (BorrowDao) BeanUtil.getBean("borrowDao");
			Borrow borrow = borrowDao.find(data.getId());
			this.data = data;
			this.data.setUser(borrow.getUser());
			this.data.setVouchFirm(borrow.getVouchFirm());
		} else {
			this.data = data;
		}
		this.flag = flag;
		this.config = config;
	}

	public BaseBorrowWorker(Borrow data, BorrowConfig config) {
		if (data != null && data.getId() > 0) {
			BorrowDao borrowDao = (BorrowDao) BeanUtil.getBean("borrowDao");
			Borrow borrow = borrowDao.find(data.getId());
			this.data = data;
			this.data.setUser(borrow.getUser());
			this.data.setVouchFirm(borrow.getVouchFirm());
		} else {
			this.data = data;
		}
		this.config = config;
	}

	@Override
	public Borrow prototype() {
		return data;
	}

	@Override
	public BorrowConfig getBorrowConfig() {
		return config;
	}

	private boolean isTrial() {
		if (config.isTrail() == false) {
			return false;
		}
		return true;
	}

	@Override
	public void setBorrowField(User user) {
		data.setRepaymentAccount(interestCalculator().repayTotal());
		data.setUser(user);
		// data.getUser().setUserId(user.getUserId());

		data.setAddIp(Global.getIP());
		data.setAddTime(DateUtil.getNow());
	}

	/** 根据系统参数中的配置决定是否跳过初审 **/
	@Override
	public void skipTrial(Borrow borrow) {
		if (this.isTrial()) {
			/*int enableAutoTender = Global.getInt("enableAutoTender");*/
			data.setStatus(1);
			/*if (enableAutoTender == 1) {*/
			// 配置自动投标规则
			AutoTenderConfRuleCheck autoCheck = RuleCheckHelper.getValue(AutoTenderConfRuleCheck.class);
			if (autoCheck != null) {
				if (autoCheck.enable_auto_tender.contains(data.getType()) && StringUtil.isBlank(borrow.getPwd())
						&& borrow.getCategory().intValue() == 1 && (borrow.getPutStartTime()==null||(borrow.getPutStartTime().getTime()<=DateUtil.getNow().getTime()))) {
					data.setStatus(19);
					if (StringUtil.isBlank(data.getPwd()) && borrow.getType() != BorrowType.TYPE_SECOND && borrow.getCategory() == BorrowCategory.NEW)  {//新手标
						try {
							BorrowModel borrowModel = BorrowModel.instance(data);
							borrowModel.setUserId(data.getUser().getUserId());
							ConcurrentUtil.autoTender(borrowModel);
						} catch (Exception e) {
							logger.error("触发disruptor自动投标异常");
						}
					}
				}
			}
			/*}*/
			VerifyLog verifyLog = new VerifyLog(new Operator(1), "borrow", borrow.getId(), 1, 1, "跳过初审");
			VerifyLogDao verifyLogDao = (VerifyLogDao) BeanUtil.getBean("verifyLogDao");
			verifyLogDao.save(verifyLog);
		}
	}

	@Override
	public void trial() {

	}

	@Override
	public void verify() {

	}

	@Override
	public void skipReview() {
		if (review()) {
			data.setStatus(BorrowStatus.STATUS_RECHECK_PASS);
			data.setReviewTime(DateUtil.getNow());
			VerifyLog verifyLog = new VerifyLog(new Operator(1), VerifyLogType.BORROW, data.getId(),
			        VerifyType.RECHECK, VerifyResult.PASS, "跳过复审");
			VerifyLogDao verifyLogDao = (VerifyLogDao) BeanUtil.getBean("verifyLogDao");
			verifyLogDao.save(verifyLog);
		}
	}

	public boolean review() {
		if (config == null || config.isReview() == false) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 * 撤回
	 */
	@Override
	public void revokeBorrow() {
		if (this.data.getRepaymentAccount() == -1) { // 前台撤标
			if (this.data.getStatus() != 0) {
				throw new BorrowException("借款标的状态不允许撤回", 1);
			}
		} else { // 后台撤标
			if (this.data.getStatus() != 1 && this.data.getStatus() != 0 && this.data.getStatus() != -2) {
				throw new BorrowException("借款标的状态不允许撤回", 1);
			}
		}
	}

	/**
	 * 秒标初审不通过解冻资金
	 */
	@Override
	public void secondUnVerifyFreeze() {

	}

	/**
	 * 计算借款标的利息
	 */
	@Override
	public double calculateInterest() {
		InterestCalculator ic = interestCalculator();
		double interest = ic.repayTotal() - data.getAccount();
		return interest;
	}

	/**
	 * 待收利息
	 */
	@Override
	public double calculateInterest(double validAccount) {
		InterestCalculator ic = interestCalculator(validAccount);
		double interest = 0;
		interest = ic.repayTotal() - validAccount;
		return interest;
	}

	@Override
	public InterestCalculator interestCalculator() {
		return interestCalculator(data.getAccount());
	}

	@Override
	public InterestCalculator interestCalculator(double validAccount) {
		InterestCalculator ic = null;
		double apr = data.getApr() / 100;
		Date date = null;
		VerifyLogDao verifyLogDao = (VerifyLogDao) BeanUtil.getBean("verifyLogDao");
		VerifyLog verifyLog = null;
		long id = data.getId();
		if (flag) {
			verifyLog = verifyLogDao.findByType(id, VerifyLogType.BORROW, VerifyType.RECHECK); // 2:复审
		} else {
			verifyLog = verifyLogDao.findByType(id, VerifyLogType.BORROW, VerifyType.TRIAL); // 1:初审
		}
		if (null != verifyLog
				&& null != verifyLog.getTime()) {
			date = verifyLog.getTime();
		} else {
			date = DateUtil.getNow();
		}
		int style = data.getStyle();
		int borrowTimeType = data.getBorrowTimeType();
		if (BorrowTimeType.DAY == borrowTimeType
				&& BorrowStyle.STYLE_ONETIME_REPAYMENT == style) { // 天标,一次性还款
			ic = new OnetimeRepaymentCalculator(validAccount, apr, date, 1, 0);
		} else if (BorrowStyle.STYLE_ONETIME_REPAYMENT == style) { // 一次性还款
			ic = new OnetimeRepaymentCalculator(validAccount, apr, date, data.getTimeLimit(), 0);
		} else if (BorrowStyle.STYLE_MONTHLY_INTEREST == style) { // 每月还息到期还本
			ic = new MonthlyInterestCalculator(validAccount, apr, date, data.getTimeLimit(), flag, 0);
		} else if (BorrowStyle.STYLE_INSTALLMENT_REPAYMENT == style) { // 等额本息
			ic = new InstallmentRepaymentCalculator(validAccount, apr, date, data.getTimeLimit(), 0);
		}
		if (BorrowTimeType.DAY == borrowTimeType) {
			ic.calculator(data.getTimeLimit());
		} else {
			ic.calculator();
		}
		return ic;
	}
	
	@Override
	public InterestCalculator exInterestCalculator(double validAccount,Date tenderAddTime) {
		double apr = data.getApr() / 100;
		if (data.getBorrowTimeType() != 1 || data.getStyle() != BorrowStyle.STYLE_ONETIME_REPAYMENT) {
			throw new BorrowException("该体验标的还款方式错误！");
		}
        InterestCalculator ic = new OnetimeRepaymentCalculator(validAccount, apr, tenderAddTime, 1, 0);
		if (data.getBorrowTimeType() == 1) {
			ic.calculator(data.getTimeLimit());
		} else {
			ic.calculator();
		}
		return ic;
	}

	/**
	 * 计算借款标的手续费
	 */
	@Override
	public double calculateBorrowFee() {
		return 0;
	}

	/**
	 * 计算奖励资金
	 */
	@Override
	public double calculateBorrowAward() {
		BorrowDao borrowDao = (BorrowDao) BeanUtil.getBean("borrowDao");
		Borrow borrow = borrowDao.find(data.getId());
		if (borrow != null) {
			/*
			 * if (borrow.getAward() == 1) {// 按投标金额比例 return
			 * borrow.getPartAccount() / 100 * data.getAccount(); } else if
			 * (borrow.getAward() == 2) {// 按固定金额分摊奖励 return borrow.getFunds();
			 * }
			 */
			return BigDecimalUtil.mul(data.getAccount(), borrow.getPartAccount()) / 100;
		}
		return 0.0;
	}

	@Override
	public Date getRepayTime(int period) {
		Date fullVerifyTime = DateUtil.getNow();
		if (this.data.getReviewTime() != null)
			fullVerifyTime = this.data.getReviewTime();
		Date repayDate = DateUtil.getLastSecIntegralTime(fullVerifyTime);
		if (this.data.getType() == BorrowType.TYPE_SECOND) {
			return repayDate;
		} else if (this.data.getBorrowTimeType() == 1) {
			repayDate = DateUtil.rollDay(repayDate, this.data.getTimeLimit());
			return repayDate;
		} else {
			if (this.data.getStyle() == BorrowStyle.STYLE_ONETIME_REPAYMENT) {// 一次性还款
				repayDate = DateUtil.rollMon(repayDate, this.data.getTimeLimit());
			} else if ("5".equals(this.data.getStyle())) {// 满标还息每月还息到期还本
				if (period == 0) {
					repayDate = DateUtil.rollMinute(DateUtil.getNow(), 5);// 5分钟后还款
				} else {
					repayDate = DateUtil.rollMon(repayDate, period);
				}
			} else {
				repayDate = DateUtil.rollMon(repayDate, period + 1);
			}
			return repayDate;
		}
	}

	@Override
	public Date getRepayTime(int period, BorrowModel borrowModel) {
		Date fullVerifyTime = DateUtil.getNow();
		Date reviewTime = borrowModel.getReviewTime();
		if (null != reviewTime) {
			fullVerifyTime = reviewTime;
		}
		Date repayDate = DateUtil.getLastSecIntegralTime(fullVerifyTime);
		int type = borrowModel.getType();
		if (BorrowType.TYPE_SECOND == type) {
			return repayDate;
		} else if (BorrowTimeType.DAY == borrowModel.getBorrowTimeType()) {
			repayDate = DateUtil.rollDay(repayDate, borrowModel.getTimeLimit());
			return repayDate;
		} else {
			int style = borrowModel.getStyle();
			if (BorrowStyle.STYLE_ONETIME_REPAYMENT == style) {// 一次性还款
				repayDate = DateUtil.rollMon(repayDate, borrowModel.getTimeLimit());
			} else if (BorrowStyle.STYLE_FULL_MONTHLY_INTEREST == style) {// 满标还息每月还息到期还本
				if (0 == period) {
					repayDate = DateUtil.rollMinute(DateUtil.getNow(), 5);// 5分钟后还款
				} else {
					repayDate = DateUtil.rollMon(repayDate, period);
				}
			} else {
				repayDate = DateUtil.rollMon(repayDate, period + 1);
			}
			return repayDate;
		}
	}

	@Override
	public Date getFlowRepayTime(int period) {
		Date fullVerifyTime = DateUtil.getNow();
		if (this.data.getReviewTime() != null)
			fullVerifyTime = this.data.getReviewTime();
		Date repayDate = DateUtil.getLastSecIntegralTime(fullVerifyTime);
		if (this.data.getType() == BorrowType.TYPE_SECOND) {
			return repayDate;
		} else if (this.data.getBorrowTimeType() == 1) {
			repayDate = DateUtil.rollDay(repayDate, this.data.getTimeLimit());
			return repayDate;
		} else {
			// 一次性还款
			if (this.data.getStyle() == BorrowStyle.STYLE_ONETIME_REPAYMENT) {
				repayDate = DateUtil.rollMon(repayDate, this.data.getTimeLimit());
			} else {
				repayDate = DateUtil.rollMon(repayDate, period + 1);
			}
			return repayDate;
		}
	}

	@Override
	public Date getFlowRepayTime(int period, BorrowModel borrowModel) {
		Date fullVerifyTime = DateUtil.getNow();
		Date reviewTime = borrowModel.getReviewTime();
		if (null != reviewTime) {
			fullVerifyTime = reviewTime;
		}
		Date repayDate = DateUtil.getLastSecIntegralTime(fullVerifyTime);
		int type = borrowModel.getType();
		if (BorrowType.TYPE_SECOND == type) {
			return repayDate;
		} else if (BorrowTimeType.DAY == borrowModel.getBorrowTimeType()) {
			repayDate = DateUtil.rollDay(repayDate, borrowModel.getTimeLimit());
			return repayDate;
		} else {
			int style = borrowModel.getStyle();
			if (BorrowStyle.STYLE_ONETIME_REPAYMENT == style) {// 一次性还款
				repayDate = DateUtil.rollMon(repayDate, borrowModel.getTimeLimit());
			} else {
				repayDate = DateUtil.rollMon(repayDate, period + 1);
			}
			return repayDate;
		}
	}

	private boolean toBool(String identify) {
		if (config == null || config.getIdentify() == null) {
			throw new BorrowException("该类借款标的配置参数不对！");
		}
		int i1 = Integer.parseInt(identify, 2);
		int i2 = Integer.parseInt(config.getIdentify(), 2);
		int ret = i1 & i2;
		if (ret > 0)
			return true;
		return false;
	}

	@Override
	public boolean isNeedRealName() {
		return this.toBool("100000");
	}

	@Override
	public boolean isNeedVIP() {
		return this.toBool("010000");
	}

	@Override
	public boolean isNeedEmail() {
		return this.toBool("001000");
	}

	@Override
	public boolean isNeedPhone() {
		return this.toBool("000100");
	}

	@Override
	public boolean isNeedVideo() {
		return this.toBool("000010");
	}

	@Override
	public boolean isNeedScene() {
		return this.toBool("000001");
	}

	@Override
	public boolean checkIdentify(User u) {
		return false;
	}

	@Override
	public boolean checkModelData() {
		BorrowAprLimitRuleCheck rule = RuleCheckHelper.getValue(BorrowAprLimitRuleCheck.class);
		if (rule.apr_limit.status == 1) {
			if (config != null) {
				double lowest_apr = 0;
				if (config.getLowestApr() != 0) {
					lowest_apr = config.getLowestApr();
				} else {
					lowest_apr = 0;
				}
				double most_apr = 0;
				if (config.getMostApr() != 0) {
					most_apr = config.getMostApr();
				} else {
					most_apr = 22.4;
				}
				if (data.getApr() < lowest_apr) {
					throw new BorrowException("借款利率不能低于" + lowest_apr + "%", 1);
				}
				if (data.getApr() > most_apr) {
					throw new BorrowException("借款利率不能高于" + most_apr + "%", 1);
				}
			}
		} else {
			if (data.getType()!=BorrowType.DELIVER_GOODS&&data.getApr() < 1) {
				throw new BorrowException("最低利率不能低于1%", 1);
			}
			if (data.getType() == BorrowType.TYPE_SECOND) {
				if (data.getApr() > 22.4) {
					throw new BorrowException("六个月份以内(含六个月)的贷款年利率不能高于22.4%", 1);
				}
			} else {
				int time_limit = data.getTimeLimit();
				double apr = data.getApr();
				if (time_limit <= 6 && apr > 22.4) {
					throw new BorrowException("六个月份以内(含六个月)的贷款年利率不能高于22.4%", 1);
				}
				if (time_limit <= 12 && time_limit > 6 && apr > 24) {
					throw new BorrowException("六个月至一年(含一年)的贷款年利率不能高于24%", 1);
				}
				if (time_limit <= 36 && time_limit > 12 && apr > 24.6) {
					throw new BorrowException("一年至三年(含三年)的贷款年利率不能高于24.6%", 1);
				}
				if (time_limit <= 60 && time_limit > 36 && apr > 25.6) {
					throw new BorrowException("三年至五年(含五年)的贷款年利率不能高于25.6%", 1);
				}
				if (time_limit > 60 && apr > 26.2) {
					throw new BorrowException("五年以上的贷款年利率不能高于26.2%", 1);
				}
			}
		}
		// this.limitAccount();
		return true;
	}

	@Override
	public boolean isLastPeriod(int period) {
		if (this.data.getType() == BorrowType.TYPE_SECOND || this.data.getBorrowTimeType() == 1
				|| this.data.getStyle() == BorrowStyle.STYLE_ONETIME_REPAYMENT) { // 修改判断为整数是否相等
			return true;
			// } else if (this.data.getStyle() == 5) { // 满标还息每月还息到期还本
			// return (this.data.getTimeLimit() == period);
		} else {
			return (this.data.getTimeLimit() == (period + 1));
		}
	}

	@Override
	public double getTransactionFee() {
		return 0;
	}

	@Override
	public double calculateAward() {
		return 0;
	}




	/**
	 * 投标奖励
	 */
	@Override
	public double calculateAward(double account) {
		double awardValue = 0;
		BorrowDao borrowDao = (BorrowDao) BeanUtil.getBean("borrowDao");
		Borrow borrow = borrowDao.find(data.getId());
		if (borrow != null) {
			int awardType = borrow.getAward();
			if (BorrowAwardType.SCALE_AWARD == awardType) {
				awardValue = (account * borrow.getPartAccount()) / 100;
			} else if (BorrowAwardType.SHARE_AWARD == awardType) {
				awardValue = (account * borrow.getFunds()) / borrow.getAccount();
			}
		}
		return BigDecimalUtil.round(awardValue, 2);
	}

	@Override
	public double calculateAward(double account, Borrow borrow) {
		double awardValue = 0;
		if (null != borrow) {
			int awardType = borrow.getAward();
			if (BorrowAwardType.SCALE_AWARD == awardType) {
				awardValue = (account * borrow.getPartAccount()) / 100;
			} else if (BorrowAwardType.SHARE_AWARD == awardType) {
				awardValue = (account * borrow.getFunds()) / borrow.getAccount();
			}
		}
		return BigDecimalUtil.round(awardValue, 2);
	}

	@Override
	public boolean allowFullSuccess() {
		return true;
	}

	@Override
	public double validAccount(BorrowTender tender, BorrowModel m) {
		double validAccount = 0.0;
		double tenderAccount = tender.getMoney();
		double account_val = data.getAccount();
		double account_yes_val = data.getAccountYes();
		if (tenderAccount + account_yes_val >= account_val) {
			validAccount = account_val - account_yes_val;
		} else {
			validAccount = tenderAccount;
		}

		double lowestSingleLimit = data.getLowestSingleLimit();
		double mostSingleLimit = data.getMostSingleLimit();
		if (validAccount < lowestSingleLimit && lowestSingleLimit > 0) {
			if (account_val - account_yes_val < lowestSingleLimit) {
				if (account_val - account_yes_val < validAccount) {
					validAccount = account_val - account_yes_val;
				}
			} else {
				throw new BorrowException("投标金额不能少于单笔最小限额", 1);
			}
		}
		if (mostSingleLimit > 0 && validAccount > mostSingleLimit) {
			validAccount = mostSingleLimit;
		}
		return validAccount;
	}

	public BorrowModel checkTenderBefore(BorrowModel model, double tenderMoney, User user, int flow_count) {
		AccountDao accountDao = (AccountDao) BeanUtil.getBean("accountDao");
		UserCacheDao userCacheDao = (UserCacheDao) BeanUtil.getBean("userCacheDao");
		UserIdentifyDao userIdentifyDao = (UserIdentifyDao) BeanUtil.getBean("userIdentifyDao");
		// 获取投标人的账户信息
		Account act = accountDao.findByUserId(user.getUserId());
		if (tenderMoney > act.getUseMoney()) {
			model.setMoney(act.getUseMoney());
		} else {
			model.setMoney(tenderMoney);
		}

		UserCache userCache = userCacheDao.findObjByProperty("user.userId", user.getUserId());
		UserIdentify userIdentify = userIdentifyDao.findByUserId(user.getUserId());
		if (userCache.getStatus() == 1) {
			throw new BorrowException("您账号已经被锁定，不能进行投标!", 1);
		}
		// 用户认证校验
		validBorrowTender(userIdentify);
		if (tenderMoney > act.getUseMoney()) {
			throw new BorrowException("投标金额不能大于您的可用余额！", 1);
		}
		if (tenderMoney < model.getLowestAccount() && model.getLowestAccount() > 0) {
			throw new BorrowException("投标金额不能小于最小投标额！", 1);
		}
		if (tenderMoney <= 0) {
			throw new BorrowException("投标金额必须大于0！", 1);
		}
		return model;
	}

	private void validBorrowTender(UserIdentify userIdentify) {
		AutoTenderConfRuleCheck check = RuleCheckHelper.getValue(AutoTenderConfRuleCheck.class);
		if (check != null) {
			if (check.tender_valid.status == 1) {
				if (check.tender_valid.real_enable == 1 && userIdentify.getRealNameStatus() != 1) {
					throw new BorrowException("您还未通过实名认证，投标失败！", 2);
				}
				/*if (check.tender_valid.email_enable == 1 && userIdentify.getEmailStatus() != 1) {
					throw new BorrowException("您还未通过邮箱认证，投标失败！", 2);
				}*/
				if (check.tender_valid.phone_enable == 1 && userIdentify.getMobilePhoneStatus() != 1) {
					throw new BorrowException("您还未通过手机认证，投标失败！", 2);
				}
			}
		}
	}

    @Override
    public void checkTender(BorrowModel model, User user, UserCache userCache ) {
        // PS 红包不再作为投标金额的一部分 暂时无用
//        double totalPacketMoney = model.getTotalRedEnvelopeMoney();
    	
    	// 返回地址
    	String redirectUrl = "/invest/" + model.getUuid() + "/detail.html";
    	UserCache cache = UserUtils.getUserCacheByUserId(user.getUserId());
    	if(cache.getUserType()==3) {
			BorrowService borrowService=(BorrowService) BeanUtil.getBean("borrowService");
			if (!borrowService.checkUserBorrowList(user.getUserId()))
				throw new BorrowException("你还有未完成的借款", redirectUrl);
		}
    	
    	if (model.getFixedTime() != null && DateUtil.getNow().before(model.getFixedTime())) {
			throw new BorrowException("该借款标设置了定时时间，还未到时，无法投标！", redirectUrl);
		}
    	
        AccountDao accountDao = (AccountDao) BeanUtil.getBean("accountDao");
        Account act = accountDao.findByUserId(user.getUserId());

//        UserCacheDao userCacheDao = (UserCacheDao) BeanUtil.getBean("userCacheDao");
//        UserCache userCache = userCacheDao.findObjByProperty("user.userId", user.getUserId());
        if (userCache.getStatus() == 1) {
            throw new BorrowException("您账号已经被锁定，不能进行投标!", redirectUrl);
        }

        // 用户认证校验
//        UserIdentifyDao userIdentifyDao = (UserIdentifyDao) BeanUtil.getBean("userIdentifyDao");
//        UserIdentify userIdentify = userIdentifyDao.findObjByProperty("user.userId", user.getUserId());
//        validBorrowTender(userIdentify);

        // 实际支付金额
        double actualPayMoney = model.getMoney();
        if (actualPayMoney <= 0) {
            throw new BorrowException("实际支付金额不能少于1元!", redirectUrl);
        }

        // 实际投资金额 actualTenderMoney = 投资金额(含实际支付+红包金额)+体验券金额
        double totalExperienceMoney = model.getTotalExperienceMoney();// 体验券金额
        double actualTenderMoney = BigDecimalUtil.add(actualPayMoney, totalExperienceMoney);// 投资金额+体验券金额

        // 初审通过的标 才能投
        if (model.getStatus() != 1) {
            throw new BorrowException("不能进行投标!", redirectUrl);
        }

        if (model.getUser().getUserId() == user.getUserId()) {
            throw new BorrowException("您不能投自己发布的标！", redirectUrl);
        }

        if (StringUtil.isBlank(model.getPayPwd())) {
            throw new BorrowException("交易密码不能为空!", redirectUrl);
        }

        if (!MD5.encode(model.getPayPwd()).equals(user.getPayPwd())) {
            throw new BorrowException("交易密码不正确!", redirectUrl);
        }

        // 标的总额
        double tenderTotalAmount = model.getAccount();
        // 已投金额
        double tenderYesAmount = model.getAccountYes();
        if (tenderYesAmount >= tenderTotalAmount) throw new BorrowException("此标已满!", redirectUrl);

        // 最小投标额
        double tenderLowestAmount = model.getLowestAccount();
        // 总额 - 已投 = 可投 >= 最小投标额
        if (BigDecimalUtil.sub(tenderTotalAmount, tenderYesAmount) >= tenderLowestAmount) {
            if (actualTenderMoney < tenderLowestAmount && tenderLowestAmount > 0) {
                throw new BorrowException("实际投标金额不能小于最小投标额！", redirectUrl);
            }
        }

        // PS 红包不再作为投标金额的一部分
//      if (BigDecimalUtil.sub(tenderNum, totalPacketMoney) > act.getUseMoney()) {
//			throw new BorrowException("您的可用余额不足，投标失败！ ", redirectUrl);
//		}
        if (actualPayMoney > act.getUseMoney()) {
            throw new BorrowException("您的可用余额不足，投标失败！ ", redirectUrl);
        }

		// 第三方可用余额判断
		TppModel tppModel = new TppModel();
		tppModel.setUser(user);
		TppBaseInterface tppService = TppServiceFactory.newIntance();
		TppAccountModel tppAccount = (TppAccountModel) tppService.tppQueryBalance(tppModel);
		if (actualPayMoney > Double.valueOf(tppAccount.getUserMoney()).doubleValue()) {
			throw new BorrowException("您的托管资金还存在未处理记录，请耐心等待！ ", redirectUrl);
		}

		// 单笔最大投标金额
        double mostSingleAccountNum = data.getMostSingleLimit();
        if (mostSingleAccountNum > 0 && actualTenderMoney > mostSingleAccountNum) {
            throw new BorrowException("实际投标金额不能大于单笔最多投标总额，投标失败！ ", redirectUrl);
        }
        
     // 排除体验标
    	// 累积最大投标金额
        double mostTenderMoney = data.getMostAccount();

        // 已经投标的金额
        BorrowTenderDao tenderDao = (BorrowTenderDao) BeanUtil.getBean("borrowTenderDao");
        double hasTenderMoney = tenderDao.hasTenderTotalPerBorrowByUserid(data.getId(), user.getUserId());

        // 投标金额不能 超过 剩余最大累积可投金额（最大投标金额 - 已投金额）
        double remainderCanMostTenderMoney = mostTenderMoney - hasTenderMoney;
        if (mostTenderMoney > 0 && actualTenderMoney > remainderCanMostTenderMoney) {
            if (remainderCanMostTenderMoney == 0) {
                throw new BorrowException("您对该标的投资已达到最多投标总额(￥" + mostTenderMoney + ")，不能继续投标，投标失败！", redirectUrl);
            }
            throw new BorrowException("实际投标金额不能大于最大投标额,您当前还可以投" + remainderCanMostTenderMoney + "元", "/invest/" + model.getUuid() + "/detail.html");
        }

        // 不能大于 剩余可投金额
        double remainderCanTenderMoney = tenderTotalAmount - tenderYesAmount;
        if (actualTenderMoney > remainderCanTenderMoney) {
            throw new BorrowException("实际投标金额不能大于可投金额,您当前还可以投" + remainderCanTenderMoney + "元", "/invest/" + model.getUuid() + "/detail.html");
        }

        // 红包规则校验
        String redPacketsUseRule = SystemConfigHelper.getValue(Nid.RED_PACKETS_RULE);
        if (SystemConfigHelper.getStatus(Nid.RED_PACKETS_RULE) == 1 && !StringUtil.isBlank(redPacketsUseRule)) {// 规则是否启用
            double totalRedEnvelopeMoney = model.getTotalRedEnvelopeMoney();// 使用红包总额
            String redPacketsRuleList[] = redPacketsUseRule.split(",");
            for (int i = 0; i < redPacketsRuleList.length; i++) {
                String redPacketsRules[] = redPacketsRuleList[i].split("\\^");
                if (redPacketsRules.length < 3) {
                    throw new BorrowException("使用红包异常，请联系客服", redirectUrl);
                }
                double canUseLowerLimit = Double.parseDouble(redPacketsRules[0]);
                double canUseUpperLimit = Double.parseDouble(redPacketsRules[1]);
                double canUseRedPacket = Double.parseDouble(redPacketsRules[2]);
                if (canUseLowerLimit < actualPayMoney && actualPayMoney <= canUseUpperLimit) {
                    if (totalRedEnvelopeMoney > canUseRedPacket) {
                        throw new BorrowException("您当前投标金额只能使用包含" + canUseRedPacket + "元以下的红包！", redirectUrl);
                    }
                }
                if (i == redPacketsRuleList.length - 1 && canUseUpperLimit < actualPayMoney) {// 校验范围以外的情况,不能超出红包允许最大范围
                    if (totalRedEnvelopeMoney > canUseRedPacket ) {
                        throw new BorrowException("您当前投标金额只能使用包含" + canUseRedPacket + "元以下的红包！", redirectUrl);
                    }
                }
            }
        }
    }
    
    @Override
    public void checkExperienceTender(BorrowModel model, User user, UserCache userCache ) {
    	
    	// 返回地址
    	String redirectUrl = "/invest/" + model.getUuid() + "/detail.html";
    	
    	if(userCache.getUserType() == UserType.INVESTMENT_BORROWER) {
    		BorrowService borrowService = (BorrowService) BeanUtil.getBean("borrowService");
    		if (!borrowService.checkUserBorrowList(user.getUserId()))
    			throw new BorrowException("你还有未完成的借款", redirectUrl);
    	}
    	
    	if (model.getFixedTime() != null && DateUtil.getNow().before(model.getFixedTime())) {
    		throw new BorrowException("该借款标设置了定时时间，还未到时，无法投标！", redirectUrl);
    	}
    	
    	if (userCache.getStatus() == 1) {
    		throw new BorrowException("您账号已经被锁定，不能进行投标!", redirectUrl);
    	}
    	
    	// 初审通过的标 才能投
    	if (model.getStatus() != 1) {
    		throw new BorrowException("不能进行投标!", redirectUrl);
    	}
    	
    	if (model.getUser().getUserId() == user.getUserId()) {
    		throw new BorrowException("您不能投自己发布的标！", redirectUrl);
    	}
    	
    	if (StringUtil.isBlank(model.getPayPwd())) {
    		throw new BorrowException("交易密码不能为空!", redirectUrl);
    	}
    	
    	if (!MD5.encode(model.getPayPwd()).equals(user.getPayPwd())) {
    		throw new BorrowException("交易密码不正确!", redirectUrl);
    	}
        // 体验金金额校验
        if (model.getExperiences().length > 1) {
            throw new BusinessException("投标失败，只能使用一张体验券！", BusinessException.TYPE_JSON);
        }

        if ((StringUtil.isBlank(model.getExperiences())) || (model.getTotalExperienceMoney() <= 0) || (model.getMoney() <= 0)) {
            throw new BusinessException("投标失败，请使用正确的体验券！", BusinessException.TYPE_JSON);
        }
    }

	@Override
	public void checkTender(BorrowTender tender) {
		UserIdentifyDao userIdentifyDao = (UserIdentifyDao) BeanUtil.getBean("userIdentifyDao");
		AccountDao accountDao = (AccountDao) BeanUtil.getBean("accountDao");
		// BorrowDao borrowDao = (BorrowDao) BeanUtil.getBean("borrowDao");
		BorrowTenderDao tenderDao = (BorrowTenderDao) BeanUtil.getBean("borrowTenderDao");
		Account act = accountDao.findByUserId(tender.getUser().getUserId());
		UserIdentify attestation = userIdentifyDao.findObjByProperty("user.userId", tender.getUser().getUserId());
		Borrow borrow = tender.getBorrow();
		// 投标校验
		BorrowModel model = BorrowModel.instance(borrow);
		model.validBorrowStatus(model, attestation);
		// 资金校验
		double account = tender.getAccount();
		if (account > act.getUseMoney()) {
			throw new BorrowException("您的可用余额不足，投标失败！ ", 1);
		}
		double lowest_single_limit = data.getLowestSingleLimit();
		if (lowest_single_limit > 0 && account < lowest_single_limit || account <= 0) {
			throw new BorrowException("投标金额不能小于单笔最低投标金额，投标失败！ ", 1);
		}
		double most_single_account_num = data.getMostSingleLimit();
		if (most_single_account_num > 0 && account > most_single_account_num || account <= 0) {
			throw new BorrowException("投标金额不能大于单笔最多投标总额，投标失败！ ", 1);
		}
		double most_account_num = data.getMostAccount();
		double hasTender = tenderDao.hasTenderTotalPerBorrowByUserid(data.getId(), tender.getUser().getUserId());
		if (most_account_num > 0 && account + hasTender > most_account_num) {
			double difference = most_account_num - hasTender;
			if (difference == 0) {
				throw new BorrowException("您对该标的投资已达到最多投标总额(￥" + most_account_num + ")，不能继续投标，投标失败！", 1);
			}
			throw new BorrowException("投标金额不能大于最大投标额,您当前还可以投" + difference + "元", 1);
		}
	}

	/**
	 * 发标前校验
	 */
	@Override
	public boolean allowPublish(User user) {
		UserIdentifyDao userIdentifyDao = (UserIdentifyDao) BeanUtil.getBean("userIdentifyDao");
		UserIdentify ua = userIdentifyDao.findByUserId(user.getUserId());
		if (isNeedRealName() && ua.getRealNameStatus() != 1) {
			throw new BorrowException("需要通过实名认证！", "/member/security/setting.html","立刻认证");
		}
		if (isNeedPhone() && ua.getMobilePhoneStatus() != 1) {
			throw new BorrowException("需要通过手机认证！", "/member/security/setting.html","立刻认证");
		}
		return true;
	}

	@Override
	public BorrowTender tenderSuccess(BorrowTender tender, InterestCalculator ic) {
		BorrowTenderDao tenderDao = (BorrowTenderDao) BeanUtil.getBean("borrowTenderDao");
        // 总共需要还款金额
        double repayment_account = ic.repayTotal();
        // tender标利息总和
        double totalInterest = BigDecimalUtil.sub(repayment_account, tender.getAccount());
		tender.setRepaymentAccount(repayment_account);
		tender.setInterest(totalInterest);
		tender.setStatus(BorrowTenderStatus.PROCESSED);
		tenderDao.modifyBorrowTender(tender);
		return tender;
	}
	
	@Override
	public BorrowTender experienceTenderSuccess(BorrowTender tender, InterestCalculator ic) {
		BorrowTenderDao tenderDao = (BorrowTenderDao) BeanUtil.getBean("borrowTenderDao");
		// 总共需要还款金额
		double repayment_account = ic.repayTotal();
		// tender标利息总和
		double totalInterest = BigDecimalUtil.sub(repayment_account, tender.getAccount());
		tender.setRepaymentAccount(totalInterest);
		tender.setInterest(totalInterest);
		tender.setStatus(BorrowTenderStatus.SUCCESS);
		tenderDao.modifyBorrowTender(tender);
		return tender;
	}

	@Override
	public void handleExTenderAfterFullSuccess(BorrowTender tender) {
		
		BorrowTenderDao tenderDao = (BorrowTenderDao) BeanUtil.getBean("borrowTenderDao");
		User user = data.getUser();
		user.getUserName();
		User tenderUser = tender.getUser();
		tenderUser.getUserId();
		Global.setTransfer("tender", tender);
		double interest = tender.getInterest();
		
		// 生成待收利息
		Global.setTransfer("money", interest);
		AbstractExecuter waitExecuter = ExecuterHelper.getExecuter(BorrowExWaitInterestExecuter.class);
		BorrowModel model = BorrowModel.instance(data);
		waitExecuter.execute(interest, tenderUser, new User(1));
		
		// 修改Tender表中的待收利息
		tender.setWaitAccount(tender.getRepaymentAccount());
		tender.setWaitInterest(tender.getInterest());
		// 体验标还款时间 = 投标时间 + 借款期限
		Date exprepaymentTime = DateUtil.rollDay(tender.getAddTime(), model.getTimeLimit());
		tender.setRepaymentTime(exprepaymentTime);
		tenderDao.update(tender);
		
		//秒标不参与一切附加活动以及vip的升级活动
		if(tender.getBorrow().getType() != BorrowType.TYPE_SECOND){
			// 体验券处理
			Global.setTransfer("tender", tender);
			AbstractExecuter experienceFullSuccessExecuter = ExecuterHelper.getExecuter(ExperienceFullSuccessExecuter.class);
			experienceFullSuccessExecuter.execute(0, null);
		} 
	}

	@Override
	public void handleTenderVip(BorrowTender tender, User tenderUser) {
		BorrowTenderDao tenderDao = (BorrowTenderDao) BeanUtil.getBean("borrowTenderDao");
		UserVipDao userVipDao = (UserVipDao) BeanUtil.getBean("userVipDao");
		UserVipLevelDao userVipLevelDao = (UserVipLevelDao) BeanUtil.getBean("userVipLevelDao");
		UserVipGrowthLogDao userVipGrowthLogDao = (UserVipGrowthLogDao) BeanUtil.getBean("userVipGrowthLogDao");
		UserIdentifyDao userIdentifyDao = (UserIdentifyDao) BeanUtil.getBean("userIdentifyDao");
		
		UserVip userVip = UserUtils.getUserVipByUserId(tenderUser.getUserId());
		if (null == userVip) {
			userVip = userVipDao.save(new UserVip(tenderUser));
		}
		
		// 当前VIP等级
		UserVipLevel vipLevel = userVip.getUserVipLevel();
		//处理vip加息
		if(vipLevel.getExtraRate() > 0){
			Global.setTransfer("extraRate", vipLevel.getExtraRate());
			Global.setTransfer("borrowTender", tender);
			AbstractExecuter vipUpRateExecuter = ExecuterHelper.getExecuter(VipUpRateExecuter.class);
			vipUpRateExecuter.extend();
		}
		
		// 当前VIP等级成长封顶值
		double growthLimitValue = vipLevel.getGrowthLimitValue();
		// 投资标当天的成长值
		Date date = DateUtil.getNow();
		double totalMoney = userVipGrowthLogDao.getGrowthTotalByTender(tenderUser,date);
		// 当投资标当天已复审通过总额小于当前VIP等级成长封顶值，则计算本次投资实际可获得成长值
		if (totalMoney < growthLimitValue) {
			// 本次可获取成长值
			double growthValue = 0;
			
			// 投资标当天已复审通过总额与当前投资之和大于成长封顶值
			if (BigDecimalUtil.add(totalMoney, tender.getMoney()) > growthLimitValue) {
				growthValue = BigDecimalUtil.sub(growthLimitValue, totalMoney);
			} else {
				growthValue = tender.getMoney();
			}
			//vip成长值获取记录
			UserVipGrowthLog uvgl = new UserVipGrowthLog();
			uvgl.setUser(tenderUser);
			uvgl.setType(UserVipGrowthLogModel.TENDER_TYPE);
			uvgl.setOp(UserVipGrowthLogModel.OP_ADD);
			uvgl.setGrowthTotal(userVip.getGrowthValue());
			uvgl.setGrowthValue(growthValue);
			uvgl.setAddTime(date);
			
			userVip.setGrowthValue(BigDecimalUtil.add(userVip.getGrowthValue(), growthValue));
			// 获取升级后vip等级
			UserVipLevel upVipLevel = userVipLevelDao.getVipLevelByLevel(vipLevel.getLevel() + 1);
			Date d = DateUtil.getNow();
			//若当前成长值满足升级条件则升级，且赠送相应红包
			if (null != upVipLevel
					&& userVip.getGrowthValue() >= upVipLevel.getGrowthValue()) {
				//如果从0级升到1级，那么userIdentify表中vip状态更新为1
				long userId = tenderUser.getUserId();
				if (1 == upVipLevel.getLevel()) {
					userIdentifyDao.modifyVipStatus(userId, 1, 0);
				}
				//升级则发红包
				long redEnvelopeRuleId = upVipLevel.getRedEnvelopeRuleId();
				if(upVipLevel.getGiftMoney() > 0
						&& redEnvelopeRuleId > 0){
					String sourceType = UserVipLevelModel.SOURCE_TYPE;
					Global.setTransfer("redEnvelopeId", redEnvelopeRuleId);
					Global.setTransfer("toUserId", userId);
					Global.setTransfer("sourceType", sourceType);
					AbstractExecuter userRedEnvelopeExecuter = ExecuterHelper.getExecuter(UserRedEnvelopeExecuter.class);
					userRedEnvelopeExecuter.extend();
				}
				userVip.setUserVipLevel(upVipLevel);
				userVip.setVipTime(d);
			}
			// 若获取vip时间距离现在大于一年，则计算是否满足降级条件
			if (DateUtil.rollYear(d, -1).after(userVip.getVipTime())) {
				// 获取一年内投资总额
				double totalMoneyByVip = tenderDao.getTotalMoneyByUserVip(userVip);
				// 若一年内投资总额小于当前VIP所需成长值则降级
				if (totalMoneyByVip < userVip.getGrowthValue()) {
					// 获取降级级后vip等级
					UserVipLevel downVipLevel = userVipLevelDao.getVipLevelByLevel(vipLevel.getLevel() - 1);
					userVip.setUserVipLevel(downVipLevel);
					userVip.setGrowthValue(downVipLevel.getGrowthValue());
					userVip.setVipTime(d);
					//降级的操作记录
					uvgl.setOp(UserVipGrowthLogModel.OP_DOWN);
					uvgl.setGrowthTotal(downVipLevel.getGrowthValue());
					//如果降级到0级，那么vip 状态随之更新为0
					if(downVipLevel.getLevel()==0){
						userIdentifyDao.modifyVipStatus(tenderUser.getUserId(), 0, 1);
					}
				}
			}
			userVipGrowthLogDao.save(uvgl);
			userVipDao.update(userVip);
		}
	}

	@Override
	public BorrowRepayment[] getRepayment() {
		logger.info("-----产生还款计划开始----");
		InterestCalculator ic = interestCalculator();
		List<EachPlan> eachPlanList = ic.getEachPlanList();
		BorrowRepayment[] repays = new BorrowRepayment[eachPlanList.size()];

		BorrowCollectionDao collectionDao = (BorrowCollectionDao) BeanUtil.getBean("borrowCollectionDao");
		int i = 0;
		for (EachPlan mi : eachPlanList) {
			BorrowRepayment repayment = new BorrowRepayment();
			double capital = 0;
			// 待收利息总额
			double interest = 0;
			if (data.getType() == BorrowType.TYPE_SECOND) {
				Object[] capitalAndInterest = collectionDao.getCapitalAndInterestByBorrowAndPeriod(data.getId(), i);
				capital = (Double) (capitalAndInterest[0]);
				double totalInterest = (Double) (capitalAndInterest[1]);
				// 待还利息总额
				interest = BigDecimalUtil.sub(data.getRepaymentAccount(), data.getAccount());
				// 若由于四舍五入导致待还利息总额比待收利息总额多，则给最后一此投资送多余的部分，保证资金一致
				collectionDao.updateInterest(data.getId(), BigDecimalUtil.sub(interest, totalInterest));
			} else {
				interest = mi.getInterest();
				capital = mi.getCapital();
			}
			mi.setInterest(interest);
			mi.setCapital(capital);
			repayment.setUser(data.getUser());
			repayment.setBorrow(data);
			repayment.setPeriod(i++);
			repayment.setRepaymentTime(getFlowRepayTime(repayment.getPeriod()));
			double repaymentAccount = BigDecimalUtil.add(mi.getCapital(), mi.getInterest());
			repayment.setRepaymentAccount(repaymentAccount);
			double repaymengInterest = mi.getInterest();
			repayment.setInterest(repaymengInterest);
			repayment.setWebStatus(BorrowRepayment.WEB_STATUS_NORMAL);
			repayment.setCapital(mi.getCapital());
			repayment.setAddTime(DateUtil.getNow());
			repayment.setAddIp(Global.getIP());
			repays[i - 1] = repayment;
		}
		logger.info("-----产生还款计划结束----" + repays[0].toString());
		return repays;
	}

	/* 	已修改为根据用户投标记录单笔收取，该方法弃用*/
	/*@Override
	public double getManageFee() {
		double fee = 0.0;
		double account = data.getAccount();
		BorrowManageFeeRuleCheck borrowManageFeeRuleCheck = (BorrowManageFeeRuleCheck) Global.getRuleCheck("borrowManageFee");
		int cal_style = borrowManageFeeRuleCheck.cal_style;
		// 固定比例收取借款手续费
		if (cal_style == 1) {
			BorrowConfig cfg = this.config;
			if (cfg != null) {
				if (data.getBorrowTimeType() == 1) {
					fee = account * cfg.getDayManageFee() * data.getTimeLimit() / 3000;
				} else {
					fee = account * cfg.getManageFee() * data.getTimeLimit() / 100;
				}
			}
		}
		// 不固定比例收取借款手续费
		if (cal_style == 2) {
			double rate = 0.0;
			if (data.getBorrowTimeType() == 1 || (data.getBorrowTimeType() == 0 && data.getTimeLimit() == 1)) {
				// 获得一个月的利率
				rate = Double.parseDouble(borrowManageFeeRuleCheck.monthRate.month_rate.get("1"));
			} else {
				// 获得多个月的利率
				rate = Double.parseDouble(borrowManageFeeRuleCheck.monthRate.month_rate.get(data.getTimeLimit() + ""));
			}
			fee = BigDecimalUtil.round(BigDecimalUtil.mul(account, rate));
		}
		return fee;
	}*/
	
	@Override
	public double getBorrowManageFeeRate() {
		double rate = 0.0;
		BorrowManageFeeRuleCheck borrowManageFeeRuleCheck = RuleCheckHelper.getValue(BorrowManageFeeRuleCheck.class);
		int cal_style = borrowManageFeeRuleCheck.cal_style;
		// 固定比例收取借款手续费
		if (cal_style == 1) {
			BorrowConfig cfg = this.config;
			if (cfg != null) {
				if (data.getBorrowTimeType() == 1) {
					rate = cfg.getDayManageFee() * data.getTimeLimit() / 3000;
				} else {
					rate = cfg.getManageFee() * data.getTimeLimit() / 100;
				}
			}
		}
		// 不固定比例收取借款手续费
		if (cal_style == 2) {
			if (data.getBorrowTimeType() == 1 || (data.getBorrowTimeType() == 0 && data.getTimeLimit() == 1)) {
				// 获得一个月的利率
				rate = Double.parseDouble(borrowManageFeeRuleCheck.monthRate.month_rate.get("1"));
			} else {
				// 获得多个月的利率
				rate = Double.parseDouble(borrowManageFeeRuleCheck.monthRate.month_rate.get(data.getTimeLimit() + ""));
			}
		}
		return rate;
	}

	@Override
	public void immediateInterestAfterTender(BorrowTender tender) {

	}

	@Override
	public void immediateRepayAfterTender(BorrowTender tender) {

	}

	@Override
	public void immediateInviteAwardAfterTender() {

	}

	@Override
	public Borrow handleBorrowBeforePublish(Borrow borrow) {
		return borrow;
	}

	@Override
	public Borrow handleBorrowAfterPublish(Borrow borrow) {
		return borrow;
	}

	@Override
	public List<BorrowCollection> createCollectionList(BorrowTender tender, InterestCalculator ic) {
		List<BorrowCollection> collectList = new ArrayList<BorrowCollection>();
		List<EachPlan> eachPlan = ic.getEachPlanList();
		// 拼装Collection对象 批量插入还款表
		int i = 0;
		double totalInterest = 0; //利息总和
		double totalCapital =0; //本金总和
		
		for (EachPlan e : eachPlan) {
			BorrowCollection c = fillCollection(e, tender, ic);
			if (i == eachPlan.size() - 1) { // 最后一期做减法(利息做减法，本金做减法，生成最后一期的待收本金，待收利息，)
				double interest = tender.getInterest();
				//计算最后一期利息
				double different = BigDecimalUtil.sub(interest, totalInterest);
				c.setInterest(different);
				//计算最后一期本金
				double diffentCapital = BigDecimalUtil.sub(tender.getAccount(), totalCapital);
				c.setCapital(diffentCapital);
				c.setRepaymentAccount(BigDecimalUtil.add(diffentCapital, different));
			}
			totalInterest = BigDecimalUtil.add(totalInterest, e.getInterest());
			totalCapital  = BigDecimalUtil.add(totalCapital,e.getCapital());
			c.setPeriod(i++);
			collectList.add(c);
		}
		this.collectionList = collectList;
		return collectList;
	}
	
	@Override
	public List<BorrowCollection> experienceCreateCollectionList(BorrowTender tender, InterestCalculator ic) {
		List<BorrowCollection> collectList = new ArrayList<BorrowCollection>();
		List<EachPlan> eachPlan = ic.getEachPlanList();
		// 拼装Collection对象 批量插入还款表
		int i = 0;
		double totalInterest = 0; //利息总和
		double totalCapital =0; //本金总和
		
		for (EachPlan e : eachPlan) {
			BorrowCollection c = fillCollection(e, tender, ic);
			if (i == eachPlan.size() - 1) { // 最后一期做减法(利息做减法，本金做减法，生成最后一期的待收本金，待收利息，)
				double interest = tender.getInterest();
				//计算最后一期利息
				double different = BigDecimalUtil.sub(interest, totalInterest);
				c.setInterest(different);
				//计算最后一期本金
				double diffentCapital = BigDecimalUtil.sub(tender.getAccount(), totalCapital);
				c.setCapital(diffentCapital);
				c.setRepaymentAccount(BigDecimalUtil.add(different));
			}
			totalInterest = BigDecimalUtil.add(totalInterest, e.getInterest());
			totalCapital  = BigDecimalUtil.add(totalCapital,e.getCapital());
			c.setPeriod(i++);
			collectList.add(c);
		}
		this.collectionList = collectList;
		return collectList;
	}

	private BorrowCollection fillCollection(EachPlan e, BorrowTender t, InterestCalculator ic) {
		BorrowCollection c = new BorrowCollection();
		c.setBorrow(t.getBorrow());
		c.setTender(t);
		c.setInterest(e.getInterest());
		c.setCapital(e.getCapital());
		c.setRepaymentAccount(e.getTotal());
		c.setAddTime(DateUtil.getNow());
		c.setAddIp(Global.getIP());
		c.setStatus(0);
		c.setRepaymentYesAccount(0.00);
		c.setLateDays(0);
		c.setLateInterest(0.00);
		c.setUser(t.getUser());

        double borrowFee = SystemConfigHelper.getDoubleValue(SystemConfigHelper.Nid.INVESTOR_MANAGE_FEE);
        borrowFee = BigDecimalUtil.mul(c.getInterest(), BigDecimalUtil.div(borrowFee, 100));
        borrowFee = BigDecimalUtil.round(borrowFee); // 四舍五入
		c.setManageFee(borrowFee);
		return c;
	}

	public String calCollectionRepayTime(BorrowTender tender, int period) {
		String repayTime = "";
		if (data.getBorrowTimeType() == 1) {
			Date date = DateUtil.rollDay(tender.getAddTime(), data.getTimeLimit());
			repayTime = date.getTime() / 1000 + "";
		} else {
			if (BorrowStyle.STYLE_ONETIME_REPAYMENT == data.getStyle()) {
				repayTime = DateUtil.rollMonth(tender.getAddTime(), data.getTimeLimit() + "");
			} else {
				repayTime = DateUtil.rollMonth(tender.getAddTime(), period + "");
			}
		}
		return repayTime;
	}

	@Override
	public List<BorrowRepayment> createFlowRepaymentList(List<BorrowCollection> clist) {
		List<BorrowRepayment> repayList = new ArrayList<BorrowRepayment>(clist.size());
		for (BorrowCollection c : clist) {
			BorrowRepayment repay = new BorrowRepayment();
			repay.setUser(data.getUser());
			repay.setBorrow(c.getBorrow());
			repay.setPeriod(c.getPeriod());
			repay.setStatus(BorrowRepaymentStatus.STATUS_WAIT_REPAY);
			repay.setWebStatus(BorrowRepayment.WEB_STATUS_NORMAL);
			repay.setRepaymentTime(c.getRepaymentTime());
			repay.setRepaymentAccount(c.getRepaymentAccount());
			repay.setInterest(c.getInterest());
			repay.setCapital(c.getCapital());
			repay.setAddTime(c.getAddTime());
			repay.setAddIp(Global.getIP());
			repay.setTender(c.getTender());
			repayList.add(repay);
		}
		this.repaymentList = repayList;
		return repayList;
	}

	@Override
	public void validBeforeRepayment(BorrowRepayment borrowRepayment, Account account) {
		if (borrowRepayment == null || borrowRepayment.getStatus() == BorrowRepaymentStatus.STATUS_YES_REPAY) {
			throw new BorrowException("该期借款已经还款,请不要重复操作！", 1);
		}
		if (this.data.getStatus() != 6 && this.data.getStatus() != 7) {
			throw new BorrowException("当前借款标的状态不能进行还款操作！", 1);
		}
		// 还款+逾期
		double repayMoney = BigDecimalUtil.add(BigDecimalUtil.add(borrowRepayment.getRepaymentAccount(), borrowRepayment.getLateInterest()));
		if (repayMoney > account.getUseMoney()) {
			throw new BorrowException("可用不足，请充值后再进行还款！", "/member/recharge/newRecharge.html", 1);
		}
		BorrowRepaymentDao borrowRepaymentDao = (BorrowRepaymentDao) BeanUtil.getBean("borrowRepaymentDao");
		boolean hasAhead = borrowRepaymentDao.hasRepaymentAhead(borrowRepayment.getPeriod(), borrowRepayment
				.getBorrow().getId());
		if (hasAhead) {
			throw new BorrowException("还有尚未还款的借款！", 1);
		}
	}

	@Override
	public void borrowRepayHandleBorrow(BorrowRepayment repay) {
		User toUser = new User();
		toUser.setUserId(1L);
		double capital = repay.getCapital();
		double interest = repay.getInterest();
		double lateInterest = repay.getLateInterest();
		Global.setTransfer("borrow", this.data);
		
		// 从用户冻结账户中扣除还款本金
		if (capital > 0) {
			Global.setTransfer("money", capital);
			AbstractExecuter repayExecuter = ExecuterHelper.getExecuter(BorrowRepayCapitalExecuter.class);
			repayExecuter.execute(capital, data.getUser(), toUser);
		}
		
		// 扣除还款利息
		if (interest > 0) {
			Global.setTransfer("money", interest);
			AbstractExecuter interestExecuter = ExecuterHelper.getExecuter(BorrowRepayInterestExecuter.class);
			interestExecuter.execute(interest, data.getUser(), toUser);
		}
		
		// 逾期利息
		if (lateInterest > 0) {
			Global.setTransfer("money", lateInterest);
			AbstractExecuter lateExecuter = ExecuterHelper.getExecuter(BorrowRepayLateInterestExecuter.class);
			lateExecuter.execute(lateInterest, data.getUser(), toUser);

            // 网站垫付
			if (repay.getStatus() == BorrowRepaymentStatus.STATUS_INSTEAD_REPAY) {
				double money = lateInterest;
				Global.setTransfer("money", money);
				AbstractExecuter systemExecuter = ExecuterHelper.getExecuter(BorrowRepaySystemLateInterestExecuter.class);
				systemExecuter.execute(money, data.getUser(), toUser);
			} else {
				// 50%给平台
				double money = lateInterest / 2;
				Global.setTransfer("money", money);
				AbstractExecuter systemExecuter = ExecuterHelper.getExecuter(BorrowRepaySystemLateInterestExecuter.class);
				systemExecuter.execute(money, data.getUser(), toUser);
			}
		}
	}

	@Override
	public void borrowRepayHandleTender(BorrowRepayment repay) {
		BorrowTenderDao tenderDao = (BorrowTenderDao) BeanUtil.getBean("borrowTenderDao");
		BorrowCollectionDao collectionDao = (BorrowCollectionDao) BeanUtil.getBean("borrowCollectionDao");
		List<BorrowCollection> list = this.getWaitColl(repay);
	
		if (list != null && list.size() > 0) {
			Global.setTransfer("borrow", this.data);
			double totalLateAwardValue = 0;
			for (BorrowCollection borrowCollection : list) {
				// 获取对应投标对象
				BorrowTender tender = tenderDao.find(borrowCollection.getTender().getId());
				
				// 体验券本金
				ExperienceExecuter experienceExecuter =  ExecuterHelper.getExecuter(ExperienceExecuter.class);
				double experienceCapital = experienceExecuter.sumCollectionExperienceCapital(borrowCollection.getId());
				
				// 归还投资人本金 = 待收本金 - 债权转出本金 - 体验券本金
				double capital = BigDecimalUtil.add(borrowCollection.getCapital(), -borrowCollection.getBondCapital(), -experienceCapital);
				// 归还投资人利息 = 待收利息 - 债权转出利息
				double conllectionInterest = BigDecimalUtil.sub(borrowCollection.getInterest(), borrowCollection.getBondInterest());
				
				// 归还投资人本金
				if (capital > 0 || experienceCapital > 0) {
					Global.setTransfer("money", capital);
					Global.setTransfer("experienceMoney", experienceCapital);
					AbstractExecuter repayTenderExecuter = ExecuterHelper.getExecuter(BorrowRepayTenderCapitalExecuter.class);
					repayTenderExecuter.execute(capital, tender.getUser(), this.data.getUser());
				}
				
				// 归还投资人利息
				borrowCollection = getInvestRepayInterest(borrowCollection, tender);
				
				// 根据投资比例归还逾期利息
				if (repay.getLateInterest() > 0) {
					double tenderLateInterest = 0;
					// 还款给投资人逾期利息 = 还款逾期利息总额  * （用户应收利息/还款利息总额） * 逾期利息划分比例，剩余的代表给与平台
					tenderLateInterest = BigDecimalUtil.mul(repay.getLateInterest(), (BigDecimalUtil.div(conllectionInterest, repay.getInterest())), SystemConfigHelper.getDoubleValue(Nid.LATE_INTEREST_RATE));
					tenderLateInterest = BigDecimalUtil.round(tenderLateInterest);
					if (tenderLateInterest > 0) {
						Global.setTransfer("money", tenderLateInterest);
						AbstractExecuter repayTenderLateExecuter = ExecuterHelper.getExecuter(BorrowRepayTenderLateInterestExecuter.class);
						repayTenderLateExecuter.execute(tenderLateInterest, tender.getUser(), this.data.getUser());
					}
					borrowCollection.setLateDays(repay.getLateDays());
					borrowCollection.setLateInterest(tenderLateInterest);
				}

				// 更新tender
				tender.setRepaymentYesAccount(BigDecimalUtil.add(tender.getRepaymentYesAccount(), borrowCollection.getRepaymentAccount()));
				tender.setRepaymentYesInterest(BigDecimalUtil.add(tender.getRepaymentYesInterest(), conllectionInterest));
				tender.setWaitAccount(BigDecimalUtil.add(tender.getWaitAccount(), -borrowCollection.getRepaymentAccount()));
				tender.setWaitInterest(BigDecimalUtil.add(tender.getWaitInterest(), -conllectionInterest));
				tenderDao.update(tender);
				
				// 更新collection
				borrowCollection.setStatus(1);
				borrowCollection.setRepaymentYesTime(DateUtil.getNow());
				borrowCollection.setRepaymentYesAccount(BigDecimalUtil.add(capital, conllectionInterest));

				collectionDao.update(borrowCollection);
				
				//还款处理当期加息券所产生的额外收益发放业务
				Global.setTransfer("collectionId",borrowCollection.getId());
				AbstractExecuter upRateRepaySuccessExecuter = ExecuterHelper.getExecuter(UpRateRepaySuccessExecuter.class);
				upRateRepaySuccessExecuter.execute(0, repay.getUser());

				//处理vip加息业务
				Global.setTransfer("collectionId",borrowCollection.getId());
				AbstractExecuter vipUpRateRepayExecuter = ExecuterHelper.getExecuter(VipUpRateRepayExecuter.class);
				vipUpRateRepayExecuter.execute(0, repay.getUser());
				
				// 向投资人发送还款成功通知，不做任何资金处理
				Global.setTransfer("collection", borrowCollection);
				Global.setTransfer("user", tender.getUser());
				Global.setTransfer("repay", repay);
				Global.setTransfer("borrow", this.data);
				AbstractExecuter repaySuccessExecuter = ExecuterHelper.getExecuter(VipUpRateRepayExecuter.class);
				repaySuccessExecuter.execute(0, tender.getUser(), borrowCollection.getUser());
			}

			// 处理债权待还
			doBondCollection(repay);

			// 扣除发标人需要支付的还款奖励
			if (totalLateAwardValue > 0) {
				Global.setTransfer("money", totalLateAwardValue);
				AbstractExecuter lateAwardExecuter = ExecuterHelper.getExecuter(RepayDeductAwardExecuter.class);
				lateAwardExecuter.execute(totalLateAwardValue, data.getUser(), new User(SystemConfigs.ADMIN_ID));
			}
		}
		
		// 处理体验券
		Global.setTransfer("borrowId", repay.getBorrow().getId());
		Global.setTransfer("period", repay.getPeriod());
		AbstractExecuter experienceRepayExecuter = ExecuterHelper.getExecuter(ExperienceRepayExecuter.class);
		experienceRepayExecuter.execute(0, repay.getBorrow().getUser());
	}

	// 处理债权待还
	private void doBondCollection(BorrowRepayment repay) {

		BondTenderDao bondTenderDao = (BondTenderDao) BeanUtil.getBean("bondTenderDao");
		BondCollectionDao bondCollectionDao = (BondCollectionDao) BeanUtil.getBean("bondCollectionDao");
		List<BondCollection> list = bondCollectionDao.getBondCollectionList(repay.getId());
		Bond bond = null;

		if (list == null || list.size() == 0) {
			return;
		}

		for (BondCollection bondCollection : list) {
			BondTender bondTender = bondTenderDao.find(bondCollection.getBondTenderId());
			// 增加债权处理，待还本金需要扣除已经转出的债权价值
			double capital = BigDecimalUtil.sub(bondCollection.getCapital(), bondCollection.getBondCapital());
			// 增加债权处理，待还利息需要扣除已经转出的利息
			double conllectionInterest = BigDecimalUtil.sub(bondCollection.getInterest(), bondCollection.getBondInterest());
			// 归还投资人本金
			if (capital > 0) {
				Global.setTransfer("money", capital);
				AbstractExecuter repayTenderExecuter = ExecuterHelper.getExecuter(BorrowRepayTenderCapitalExecuter.class);
				repayTenderExecuter.execute(capital, bondTender.getUser(), this.data.getUser());

			}
			// 归还投资人利息
			repayBondInterest(bondCollection, bondTender);

			// 根据投资比例归还逾期利息
			if (repay.getLateInterest() > 0) {
				double tenderLateInterest = 0;
				// 逾期利息50%给平台
				tenderLateInterest = BigDecimalUtil.mul(repay.getLateInterest(), (BigDecimalUtil.div(conllectionInterest, repay.getInterest())), SystemConfigHelper.getDoubleValue(Nid.LATE_INTEREST_RATE));
				tenderLateInterest = BigDecimalUtil.round(tenderLateInterest);
				if (tenderLateInterest > 0) {
					Global.setTransfer("money", tenderLateInterest);
					AbstractExecuter repayTenderLateExecuter = ExecuterHelper.getExecuter(BorrowRepayTenderLateInterestExecuter.class);
					repayTenderLateExecuter.execute(tenderLateInterest, bondTender.getUser(), this.data.getUser());
				}
				bondCollection.setLateDays(repay.getLateDays());
				bondCollection.setLateInterest(tenderLateInterest);
			}

			bondTender.setReceivedAccount(BigDecimalUtil.add(bondTender.getReceivedAccount(), capital));
			bondTenderDao.update(bondTender);
			// 更新collection
			bondCollection.setStatus((byte) 1);
			bondCollection.setCollectionYesTime(DateUtil.getNow());
			bondCollection.setCollectionYesAccount(BigDecimalUtil.add(capital, conllectionInterest));

			// 增加债权处理，待还奖励需要扣除已经转出的奖励
			double awardValue = BigDecimalUtil.sub(bondCollection.getAward(), bondCollection.getBondAward());
			if (awardValue > 0) {
				Global.setTransfer("award", awardValue);
				AbstractExecuter awardRepayExecuter = ExecuterHelper.getExecuter(AwardRepayExecuter.class);
				awardRepayExecuter.execute(awardValue, bondTender.getUser(), this.data.getUser());
			}
			bondCollectionDao.update(bondCollection);

			// 向投资人发送还款成功通知，不做任何资金处理
			Global.setTransfer("collection", bondCollection);
			Global.setTransfer("user", bondTender.getUser());
			Global.setTransfer("repay", repay);
			if (bond == null) {
				bond = bondCollection.getBond();
			}
			Global.setTransfer("bondName", getBondName(bond));
			AbstractExecuter repaySuccessExecuter = ExecuterHelper.getExecuter(BondTenderReceiveSuccessExecuter.class);
			repaySuccessExecuter.execute(0, bondTender.getUser(), bondCollection.getUser());
		}

	}

	private String getBondName(Bond bond) {
		long maxDayId = bond.getDayId();
		Date addTime = bond.getAddTime();
		String bondName = "";
		if (maxDayId < 10) {
			bondName = DateUtil.dateStr7(addTime).substring(4) + "0" + maxDayId;
		} else {
			bondName = DateUtil.dateStr7(addTime).substring(4) + maxDayId;
		}
		return bondName;
	}

	@Override
	public void borrowPriorRepayHandleBorrow(BorrowRepayment repay) {
		BorrowRepaymentDao borrowRepaymentDao = (BorrowRepaymentDao) BeanUtil.getBean("borrowRepaymentDao");
		double waitOldRpayCapital = borrowRepaymentDao.getRemainderCapital(repay.getBorrow().getId()); // 计算剩余待还本金
		double waitRepayInterest = borrowRepaymentDao.getwaitRpayInterest(repay.getBorrow().getId(), repay.getPeriod()); // 本次提前还款待还利息总和
		User toUser = new User();
		toUser.setUserId(1L);
		Global.setTransfer("borrow", this.data);
		// 从用户冻结账户中扣除剩余还款本金
		if (waitOldRpayCapital > 0) {
			Global.setTransfer("money", waitOldRpayCapital);
			AbstractExecuter repayExecuter = ExecuterHelper.getExecuter(BorrowRepayCapitalExecuter.class);
			repayExecuter.execute(waitOldRpayCapital, data.getUser(), toUser);
		}
		// 扣除还款利息+罚息
		if (waitRepayInterest > 0 && (!(this.data.getBorrowTimeType() == 1 && this.data.getStyle() == 4))) {
			Global.setTransfer("money", waitRepayInterest);
			AbstractExecuter interestExecuter = ExecuterHelper.getExecuter(BorrowRepayInterestExecuter.class);
			interestExecuter.execute(waitRepayInterest, data.getUser(), toUser);
		}
	}

	@Override
	public void borrowPriorRepayHandleTender(BorrowRepayment repay) {
		BorrowTenderDao tenderDao = (BorrowTenderDao) BeanUtil.getBean("borrowTenderDao");
		BorrowCollectionDao collectionDao = (BorrowCollectionDao) BeanUtil.getBean("borrowCollectionDao");
		BorrowRepaymentDao borrowRepaymentDao = (BorrowRepaymentDao) BeanUtil.getBean("borrowRepaymentDao");
		AccountDao accountDao = (AccountDao) BeanUtil.getBean("accountDao");
		AccountService accountService = (AccountService) BeanUtil.getBean("accountService");
		// 获得提前还款剩余还款的本金
		double money = collectionDao.getRemainderMoney(repay.getBorrow().getId());
		List<BorrowCollection> list = this.getWaitColl(repay);
		if (list != null && list.size() > 0) {
			Global.setTransfer("borrow", this.data);
			for (BorrowCollection borrowCollection : list) {
				BorrowTender tender = tenderDao.find(borrowCollection.getTender().getId());
				double cCapital = collectionDao.getRemainderCapital(tender.getId()); // 计算投资人剩余待还本金
				double waitRepayInterest = borrowRepaymentDao.getwaitRpayInterest(repay.getBorrow().getId(), repay.getPeriod()); // 本次提前还款待还利息总和
				double nowInterest = 0; // 当期应收利息
				// 归还投资人本金
				if (cCapital > 0) {
					Global.setTransfer("money", cCapital);
					AbstractExecuter repayTenderExecuter = ExecuterHelper.getExecuter(BorrowRepayTenderCapitalExecuter.class);
					repayTenderExecuter.execute(cCapital, tender.getUser(), this.data.getUser());
				}
				// 归还投资人利息+罚息
				if (waitRepayInterest > 0) {
					double repayInterest = BigDecimalUtil.mul(waitRepayInterest, BigDecimalUtil.div(cCapital, money));

                    double borrowFee = SystemConfigHelper.getDoubleValue(SystemConfigHelper.Nid.INVESTOR_MANAGE_FEE);
                    borrowFee = BigDecimalUtil.mul(borrowCollection.getInterest(), BigDecimalUtil.div(borrowFee, 100));
                    borrowFee = BigDecimalUtil.round(borrowFee); // 四舍五入

					// 收回利息
					Global.setTransfer("money", repayInterest);
					AbstractExecuter repayTenderInterestExecuter = ExecuterHelper.getExecuter(BorrowRepayTenderInterestExecuter.class);
					repayTenderInterestExecuter.execute(repayInterest, tender.getUser(), this.data.getUser());
					double waitInterest = borrowRepaymentDao.getWaitInterest(repay.getBorrow().getId(), repay.getPeriod() + 2);
					accountService.deductTotalAndAddCollection(tender.getUser().getUserId(), this.data.getUser().getUserId(), waitInterest);
					// 扣除投资人利息管理费
					if (borrowFee > 0) {
						Global.setTransfer("money", borrowFee);
						AbstractExecuter manageFeeExecuter = ExecuterHelper.getExecuter(DeductManageFeeExecuter.class);
						manageFeeExecuter.execute(borrowFee, tender.getUser(), new User(SystemConfigs.ADMIN_ID));
						borrowCollection.setManageFee(borrowFee);
					}
					
					// 收到平台支付的VIP利息
					//payVipInterest(borrowCollection);
				}

				tender.setStatus(1);
				tender.setWaitAccount(0);
				tender.setWaitInterest(0);
				tender.setRepaymentYesAccount(cCapital);
				tender.setRepaymentYesInterest(nowInterest);
				// 更新tender记录
				tenderDao.update(tender);

				// 向投资人发送还款成功通知，不做任何资金处理
				Global.setTransfer("collection", borrowCollection);
				AbstractExecuter repaySuccessExecuter = ExecuterHelper.getExecuter(TenderRepaySuccessExecuter.class);
				repaySuccessExecuter.execute(0, tender.getUser(), borrowCollection.getUser());
			}
		}
		collectionDao.updatePriorRepayStatus(repay.getBorrow().getId());

	}

	/**
	 * 处理借款标还款利息及利息管理费
	 * 
	 * @param borrowCollection
	 * @param tender
	 * @return
	 */
	private BorrowCollection getInvestRepayInterest(BorrowCollection borrowCollection, BorrowTender tender) {
		// 归还投资人利息 = 待收利息 - 债权转出利息
		double cInterest = BigDecimalUtil.sub(borrowCollection.getInterest(), borrowCollection.getBondInterest());
		Global.setTransfer("borrow", this.data);
		// 归还投资人利息
		if (cInterest > 0) {
            double borrowFee = SystemConfigHelper.getDoubleValue(SystemConfigHelper.Nid.INVESTOR_MANAGE_FEE);
            borrowFee = BigDecimalUtil.mul(borrowCollection.getInterest(), BigDecimalUtil.div(borrowFee, 100));
            borrowFee = BigDecimalUtil.round(borrowFee); // 四舍五入

			// 收回利息
			Global.setTransfer("money", cInterest);
			Global.setTransfer("borrowFee", borrowFee);
			AbstractExecuter repayTenderInterestExecuter = ExecuterHelper.getExecuter(BorrowRepayTenderInterestExecuter.class);
			repayTenderInterestExecuter.execute(cInterest, tender.getUser(), this.data.getUser());
			
			// 扣除投资人利息管理费
			if (borrowFee > 0) {
				Global.setTransfer("money", borrowFee);
				AbstractExecuter manageFeeExecuter = ExecuterHelper.getExecuter(DeductManageFeeExecuter.class);
				manageFeeExecuter.execute(borrowFee, tender.getUser(), new User(SystemConfigs.ADMIN_ID));
				borrowCollection.setManageFee(borrowFee);
			}
		}
		return borrowCollection;
	}

	/**
	 * 处理债权转让还款利息及利息管理费
	 * 
	 * @param bondCollection
	 * @param tender
	 */
	private void repayBondInterest(BondCollection bondCollection, BondTender tender) {
		// 增加债权处理，待还利息需要扣除已经转出的利息
		double cInterest = BigDecimalUtil.sub(bondCollection.getInterest(), bondCollection.getBondInterest());
		Global.setTransfer("borrow", this.data);
		// 归还投资人利息
		if (cInterest > 0) {
			double borrow_fee = SystemConfigHelper.getDoubleValue(Nid.INVESTOR_MANAGE_FEE);
			double borrowFee = BigDecimalUtil.mul(cInterest, borrow_fee);
			borrowFee = BigDecimalUtil.round(borrowFee);
			
			// 收回利息
			Global.setTransfer("money", cInterest);
			Global.setTransfer("borrowFee", borrowFee);
			AbstractExecuter repayTenderInterestExecuter = ExecuterHelper.getExecuter(BorrowRepayTenderInterestExecuter.class);
			repayTenderInterestExecuter.execute(cInterest, tender.getUser(), this.data.getUser());
			
			// 扣除投资人利息管理费
			if (borrowFee > 0) {
				Global.setTransfer("money", borrowFee);
				AbstractExecuter manageFeeExecuter = ExecuterHelper.getExecuter(DeductManageFeeExecuter.class);
				manageFeeExecuter.execute(borrowFee, tender.getUser(), new User(SystemConfigs.ADMIN_ID));
			}
		}

	}
	
	@Override
	public void stopBorrow() {
		if (this.data.getStatus() != 1) {
			throw new BorrowException("借款标的状态不正确！", 1);
		}
		data.setOldAccount(data.getAccount());
		data.setAccount(data.getAccountYes());
		data.setScales(data.getAccountYes() / data.getAccount() * 100);
		InterestCalculator ic = interestCalculator();
		double repayAccount = ic.repayTotal();
		data.setRepaymentAccount(repayAccount);
	}

	@Override
	public void validBeforeCompensate(BorrowRepayment borrowRepayment) {
		if (borrowRepayment == null || borrowRepayment.getStatus() == BorrowRepaymentStatus.STATUS_YES_REPAY) {
			throw new BorrowException("该期借款已经还款,请不要重复操作！", 1);
		}
		if (this.data.getStatus() != 6 && this.data.getStatus() != 7) {
			throw new BorrowException("当前借款标的状态不能进行还款操作！", 1);
		}
		BorrowRepaymentDao borrowRepaymentDao = (BorrowRepaymentDao) BeanUtil.getBean("borrowRepaymentDao");
		boolean hasAhead = borrowRepaymentDao.hasRepaymentAhead(borrowRepayment.getPeriod(), borrowRepayment.getBorrow().getId());
		if (hasAhead) {
			throw new BorrowException("还有尚未还款的借款！", 1);
		}
	}

	@Override
	public BorrowRepayment repay(BorrowModel model) {
		return null;
	}

	@Override
	public void fullFailUpRateInerest() {
		Global.setTransfer("borrowId", data.getId());
		AbstractExecuter deductExecuter = ExecuterHelper.getExecuter(UpRateFullFailExecuter.class);
		deductExecuter.execute(0, null);
	}

	public List<BorrowCollection> getWaitColl(BorrowRepayment repay) {
		BorrowCollectionDao collectionDao = (BorrowCollectionDao) BeanUtil.getBean("borrowCollectionDao");
        List<BorrowCollection> collList = collectionDao.list(repay.getBorrow().getId(), repay.getPeriod());
		return collList;
	}
}
